// $Id: input_xpt.hpp 2 2009-09-02 08:47:42Z joseph2002 $
/*
 * Copyright 2009 Joseph Wu
 * Distributed under the Boost Software License, Version 1.0.
 * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
 *
 * For more information, see http://xpcomplus.sourceforge.net
 */

#ifndef XPGEN_INPUT_XPT_HPP
#define XPGEN_INPUT_XPT_HPP

#include <cstddef>
#include <set>
#include <vector>
#include <xpgen/input.hpp>

struct XPTArena;
struct XPTHeader;
struct XPTInterfaceDirectoryEntry;
struct XPTInterfaceDescriptor;
struct XPTConstDescriptor;
struct XPTMethodDescriptor;
struct XPTParamDescriptor;
struct XPTTypeDescriptor;
union XPTConstValue;

namespace xpgen {

struct interface_decl;
struct constant_decl;
struct method_decl;
struct param_decl;
struct type_decl;
union constant_value;

class input_xpt : public input
{
public:
    input_xpt();
    virtual ~input_xpt();

    // options

    // This will turn uint32 return value of [notxpcom] method into result
    // if have value parameter of uuid type (not uuid_ref of uuid_ptr)
    bool guess_notxpcom_result;

protected:
    virtual void do_reset();
    virtual void do_module();

private:
    void do_header(XPTHeader* header);
    void do_interface(interface_decl* itf);
    void do_method(method_decl* method);

    void init_root_interface(interface_decl* itf);
    void init_interface(interface_decl* itf, XPTInterfaceDirectoryEntry* ide);
    void init_constant(constant_decl* constant, XPTConstDescriptor* cd);
    void init_method(method_decl* method, XPTMethodDescriptor* md);
    void init_param(param_decl* param, XPTParamDescriptor* pd, const std::string& name);
    void init_void_retval_param(param_decl* param);
    void init_type(interface_decl* itf, type_decl* type, XPTTypeDescriptor* td);
    void init_constant_value(type_decl* type, constant_value* value, XPTConstValue* cv);

    void setup_interface(interface_decl* itf);
    void setup_param(param_decl* param);
    param_decl* get_sub_param(param_decl* param, std::size_t n) const;

    interface_decl* root_interface() const;
    interface_decl* xpt_interface(std::size_t index) const;

    enum additional_flags
    {
        flag_check_size_t = 0x01000000 // for size_t hack
    };
    static bool is_interface_need_size_t(interface_decl* itf);

    static void check_interface(XPTInterfaceDirectoryEntry* ide);
    static bool is_root_interface(XPTInterfaceDirectoryEntry* ide);
    static void check_constant(interface_decl* itf, XPTConstDescriptor* cd);
    static void check_method(interface_decl* itf, XPTMethodDescriptor* md);
    static void check_param(interface_decl* itf, XPTParamDescriptor* pd);
    static void check_type(interface_decl* itf, XPTTypeDescriptor* td);

    static void check_iid_is_param(param_decl* param);
    static void check_size_is_param(param_decl* param);

    XPTArena* arena_;
    std::vector<interface_decl*> itf_map_;
    std::set<interface_decl*> tmp_refs_;
};

} // namespace xpgen

#endif // XPGEN_INPUT_XPT_HPP
